#include "sensormanager.h"

#include <pthread.h>
#include "sys_inc.h"
#include "iot_debug.h"
#include "version.h"

#include "phylink.h"
#include "thirdparty/rapidjson/tools.h"
#include "modelmanger.h"
#include "physicallinkmanager.h"
#include "devicemanager.h"
#include "idevice.h"
#include "regbase.h"
#include "config.h"
#include "util_tools.h"
#include "modulemanager.h"

#include "sensornode.h"
#include "string_match.h"

#include <algorithm>
#include <logger.h>

using namespace rapidjson;
using namespace DC;

extern UseUart usrUart_;

sensormanager*   sensormanager::instanceM = nullptr;
MMutex           sensormanager::instanceLockM;

sensormanager* sensormanager::getInstance()
{
    if (instanceM == nullptr)
    {
        AUTO_GUARD(gd, MMutex, instanceLockM);
        if (instanceM == nullptr)
        {
            instanceM = new sensormanager();
        }
    }
    return instanceM;
}


sensormanager::sensormanager() :
    DataCenter (),
    isReport(false),
    isSYMC(false),
    needCheckDevs_(true),
    restartFlag_(false)
{
}

sensormanager::~sensormanager()
{

}

void sensormanager::startServer()
{
    pthread_t handler_t;
    pthread_create(&handler_t, nullptr, serverThread, this);
}

void sensormanager::startSMYL()
{
    isSYMC = true;
    if (logined())
    {
        SubRemoteServiceInit();
        SubRemoteServiceHandle();
    }
}

void sensormanager::startReport()
{
    isReport = true;
    if (logined())
    {
        SubYKCmdTopic();
    }
}

void* sensormanager::serverThread(void *argv)
{
    sensormanager *pManger = reinterpret_cast<sensormanager *>(argv);
    pManger->handle();
    return NULL;
}

void sensormanager::handle()
{
    uint64_t RealdataTime = 0;
    uint64_t OfflineStateTime = 0;
    uint64_t OnlineStateTime = 0;
    uint64_t CheckDeviceTime = 0;
    uint64_t CheckDeviceCnt = 0;
    int ReportType = 0;
    std::string starttime;
    std::string t_time;
    IDevice::Datas regs_;

    OfflineStateTime = getMilliseconds();
    CheckDeviceTime = getMilliseconds() + 1000;
    CheckDeviceCnt = 0;

    while (true)
    {
        if (!logined())
        {
            deinit();
            //mqtt客户端断开连接,需进行重连
            init(APP_NAME);
            sleep(1);
            if (logined() && isReport)
            {
                RealdataTime = OfflineStateTime = OnlineStateTime = 0;

                //掉线需要重新注册全部topic
                SubYKCmdTopic();
                SubRemoteServiceInit();
                SubRemoteServiceHandle();
            }
            continue;
        }

        if (isReport)
        {
            //Cnt1为定时上报计数,Cnt2为上报南向设备离线状态计数,Cnt3为上报南向设备在线状态计数
            uint64_t curTime = getMilliseconds();

            if ((RealdataTime + g_config.Realdata_Reportperiod * 1000) < curTime)
            {
                RealdataTime = curTime;

                //定时写实时数据
                ReportType = 1;
            }
            else
            {
                ReportType = 0;
            }

            if ((OfflineStateTime + g_config.OfflineState_Reportperiod * 1000) < curTime)
            {
                OfflineStateTime = curTime;

                for (auto it=sensors_.begin(); it!=sensors_.end(); ++it)
                {
                    IDevice *dev = it->first;
                    if (!dev->isActived() && dev->Regstatus)
                    {
                        //设备离线
                        for (auto its=it->second.begin(); its!=it->second.end(); ++its)
                        {
                            starttime = dev->getOfflineTime();
                            BoardCastsendDevState(*its, starttime, 0);
                            SendDevState(*its, 0);
                        }
                    }
                }
            }

            if ((OnlineStateTime + g_config.OnlineState_Reportperiod * 1000) < curTime)
            {
                OnlineStateTime = curTime;

                for (auto it = sensors_.begin(); it != sensors_.end(); ++it)
                {
                    IDevice *dev = it->first;
                    if (dev->isActived() && dev->getOnlineState() && dev->Regstatus)
                    {
                        //设备在线
                        for (auto its=it->second.begin(); its!=it->second.end(); ++its)
                        {
                            starttime = dev->getOnlineTime();
                            BoardCastsendDevState(*its, starttime, 1);
                            SendDevState(*its, 1);
                        }
                    }
                }
            }

            if ((CheckDeviceTime + CheckDeviceCnt * 1000) < curTime)
            {
                CheckDeviceTime = curTime;

                ++CheckDeviceCnt;
                if (CheckDeviceCnt > 3) CheckDeviceCnt = 3;

                for (auto it = sensors_.begin(); it != sensors_.end(); ++it)
                {
                    IDevice *dev = it->first;

                    if (dev->Regstatus)
                    {
                        continue;
                    }

                    dev->getAllRegs(regs_);

                    for (IDevice::Datas::iterator it2 = regs_.begin(); it2 != regs_.end(); ++it2)
                    {
                        RegBase* reg = (RegBase*)*it2;
                        if (reg->status() != RegBase::INIT)
                        {
                            //说明已经完成一轮完整数据采集
                            dev->Regstatus = true;
                            break;
                        }
                    }

                    //开机第一个采集已经结束,检查是否已经上线
                    if (dev->Regstatus && dev->isActived())
                    {
                        t_time = DataCenter::GetTimeStamp();
                        dev->setOnlineTime(t_time);
                        dev->setOnlineState(true);

                        for (auto its = sensors_[dev].begin(); its != sensors_[dev].end(); ++its)
                        {
                            BoardCastsendDevState(*its, t_time, 1);
                            SendDevState(*its, 1);
                        }

                        sendData(dev, sensors_[dev], true, ReportType, t_time);
                    }
                }
            }

            for (auto it = sensors_.begin(); it != sensors_.end(); ++it)
            {
                IDevice *dev = it->first;

                //初始化状态为false,此时未进行一轮数据采集
                if(!dev->Regstatus)
                {
                    continue;
                }

                if (dev->isActived() && dev->getOnlineState())
                {
                    //设备正常在线,检查发送数据
                    sendData(dev, it->second, false, ReportType, dev->getOnlineTime());
                }
                else
                {
                    //设备离线
                    if (!stl_containof(offline_devs_, dev))
                    {
                        t_time = DataCenter::GetTimeStamp();
                        dev->setOnlineState(false);
                        dev->setOfflineTime(t_time);
                        offline_devs_.push_back(dev);
                        for (auto its=it->second.begin(); its!=it->second.end(); its++)
                        {
                            BoardCastsendDevState(*its, t_time, 0);
                            SendDevState(*its, 0);
                        }
                        //出现在线设备发生离线.统一上报失效数据
                        sendData(dev, sensors_[dev], true, false, t_time);
                    }
                }
            }

            for (auto it = offline_devs_.begin(); it != offline_devs_.end(); )
            {
                IDevice *dev = *it;
                if (dev->isActived())
                {
                    //设备离线后又上线
                    t_time = DataCenter::GetTimeStamp();
                    dev->setOnlineTime(t_time);
                    dev->setOnlineState(true);

                    for (auto its = sensors_[dev].begin(); its != sensors_[dev].end(); ++its)
                    {
                        BoardCastsendDevState(*its, t_time, 1);
                        SendDevState(*its, 1);
                    }

                    sendData(dev, sensors_[dev], true, ReportType, t_time);
                    it = offline_devs_.erase(it);
                }
                else
                {
                    //设备一直离线
                    ++it;
                }
            }
        }

        if (isSYMC)
        {
            if (needCheckDevs_)
            {
                needCheckDevs_ = false;
                if (registerDevInfos_.size() == 0)
                {
                    getRegister();
                }
                else
                {
                    bool isDelete(false);
                    for (DC::DevInfos::iterator info = registerDevInfos_.begin(); info != registerDevInfos_.end(); ++info)
                    {
                        bool found(false);
                        for (mapSensors::iterator it = sensors_.begin(); it != sensors_.end(); ++it)
                        {
                            for (Sensors::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
                            {
                                DevInfo& dev_info = (*it2)->devInfo();
                                if (info->model == dev_info.model &&
                                    info->port == dev_info.port   &&
                                    info->addr == dev_info.addr   &&
                                    info->desc == dev_info.desc)
                                {
                                    found = true;
                                    goto CHECK_REG_END;
                                }
                            }
                        }
                    CHECK_REG_END:
                        if (found == false)
                        {
                            unregisterDev(info->model, info->port, info->addr, info->desc);
                            registerDevInfos_.erase(info);
                            isDelete = true;
                            break;
                        }
                    }

                    if (isDelete)
                    {
                        needCheckDevs_ = true;
                    }
                    else
                    {
                        registerDevInfos_.clear();
                    }
                }
            }
        }

        //检查模组信息文件[台区终端]
        if (ModuleManager::getInstance()->loop())
        {
            //映射文件已经更新,需要更新内部串口设备节点
            PhysicalLinkManager::mgr()->updateRemapCom();
        }

        //检查zLog配置，重新加载打印等级
        Logger::getInstance()->reload();

        if (restartFlag_)
        {
            log_info("SyyGather will reboot due to SMYL.");
            exit(0);
        }
        else{}

        mSleep(100);
    }
}

bool sensormanager::loadSensors()
{
    std::string filename;
    int32_t uart_index;

    ////加载本地工程设备
    filename = std::string(DATACENTERMODEL_PATH "SouthDeviceList.json");
    Document doc;
    Value *js = nullptr;

    if (parseFile(filename.c_str(), doc) != true)
    {
        FILE * fp = fopen(filename.c_str(), "r");
        if (fp == NULL)
        {
            ErrCode = OPEN_SOUTHDEVICELIST_FAIL;
        }
        else
        {
            fclose(fp);
            ErrCode = PARSE_SOUTHDEVICELIST_FAIL;
        }

        Print_err_log(ErrCode);
        goto exitCode;
    }

    js = getChild(doc, "DeviceList");
    for (auto it=js->Begin(); it!=js->End(); it++)
    {
        SensorNode * sensor = loadSensor(it, 0);
        if (sensor == nullptr)
            goto exitCode;

        auto it_s = sensors_.find(sensor->dev());
        if (it_s != sensors_.end())
        {
            it_s->second.push_back(sensor);
        }
        else
        {
            Sensors s;
            s.push_back(sensor);
            sensors_[sensor->dev()] = s;
        }
    }

    return true;
exitCode:
    return false;
}

bool sensormanager::clearSensors()
{
    needCheckDevs_ = false;
    sensors_.clear();
    return true;
}

bool sensormanager::checkUartInfo(void)
{
    for (uint32_t i = 0; i < usrUart_.size(); i++)
    {
        getUartInfo(usrUart_[i]->uart_name.c_str(), 6);
        getUartMode(*usrUart_[i]);
        if ((usrUart_[i]->app_name != APP_NAME) &&
            (usrUart_[i]->mode.find("only") != std::string::npos))
        {
            //该串口已经被其它app占用
            ErrCode = REGISTER_UART_FAIL;
            log_info("%s used Uart %s\n", usrUart_[i]->app_name.c_str(), usrUart_[i]->uart_name.c_str());
            sprintf(ErrMsg, "%s used Uart %s\n", usrUart_[i]->app_name.c_str(), usrUart_[i]->uart_name.c_str());
            Print_err_log_msg(ErrCode, ErrMsg);
            goto exitCode;
        }
        else if (usrUart_[i]->mode.find("only") != std::string::npos)
        {
            //串口未占用,设置串口为独占模式
            setUart(usrUart_[i]);
        }
        else{}
    }

    return true;
exitCode:
    return false;
}

bool sensormanager::checkModels()
{
    RegisterModels Reregistered_models;

    std::list<std::string> models, registered_models;
    bool ret = false;
    int cnt = 0;

    do
    {
       ret = getModelSchema(10);
       ++cnt;
    }while(!ret && cnt < 3);

    if (ret == false)
    {
        sprintf(ErrMsg, "Get model failed\n");
        log_info("%s\n", ErrMsg);
        goto exitCode;
    }

    ModelManger::mgr()->getModelNames(models);

    //models为project/DataCenter中模型文件名称
    for (auto m=models.begin(); m!=models.end(); )
    {
        if (hasModelName(*m))
        {
            //registered_models为数据库中已注册的模型文件
            registered_models.push_back(*m);
            m = models.erase(m);
        }
        else
            m++;
    }

    //models为数据中心未注册模型文件,开始往数据中心注册
    if (models.size())
    {
        for (auto m=models.begin(); m!=models.end(); m++)
        {
            const ModelItems * items = ModelManger::mgr()->node(m->c_str());
            ret = setModel(m->c_str(), *items);
            if(!ret)
            {
                sprintf(ErrMsg, "Register mode %s failed\n", m->c_str());
                ErrCode = REGISTER_MODE_FAIL;
                Print_err_log_msg(ErrCode, ErrMsg);
                log_info("%s\n", ErrMsg);
                goto exitCode;
            }
            usleep(5000);
        }
    }

    //检查数据中心已注册模型文件内容和project/DataCenter中模型内容是否匹配
    if (registered_models.size())
    {
        for (auto m=registered_models.begin(); m!=registered_models.end(); m++)
        {
            getModel(m->c_str());
            usleep(5000);
        }

        time_t t0 = getCurrentTime();
        do
        {
            mtx_.lock();
            for (auto m=registered_models.begin(); m!=registered_models.end(); )
            {
                if (hasModel(*m))
                {
                    //dc_model为数据中心注册模型文件,dev_model为project/DataCenter中模型文件
                    const ModelItems * dc_model = findModel(*m);
                    const DC::ModelItems * dev_model = ModelManger::mgr()->node(m->c_str());
                    for (auto it = dev_model->begin(); it != dev_model->end(); ++it)
                    {
                        if (!containedItem(*dc_model, *it))
                        {
                            log_info("DataCenter mode %s not containded %s\n", m->c_str(), it->name.c_str());
                            //把需要重新注册的模型文件写入Reregistered_models中
                            if (Reregistered_models.find(*m) != Reregistered_models.end())
                            {
                                Reregistered_models[*m].push_back(*it);
                            }
                            else
                            {
                                DC::ModelItems items;
                                items.push_back(*it);
                                Reregistered_models[*m] = items;
                            }
                        }
                        else{}
                    }
                    m = registered_models.erase(m);
                }
                else
                    m++;
            }
            mtx_.unlock();
            if (registered_models.empty())
                break;
            usleep(10000);
        } while (!checkTime(t0, getCurrentTime(), 10));

        if (registered_models.size())
        {
            ErrCode = REGISTER_MODE_FAIL;
            Print_err_log(ErrCode);
            goto exitCode;
        }
    }

    if (Reregistered_models.size())
    {
        for (auto m=Reregistered_models.begin(); m!=Reregistered_models.end(); m++)
        {
            //重新注册模型文件
            log_info("Reregister mode %s\n", m->first.c_str());
            ret = setModel(m->first.c_str(), m->second);
            if(!ret)
            {
                sprintf(ErrMsg, "Register mode %s failed\n", m->first.c_str());
                ErrCode = REGISTER_MODE_FAIL;
                Print_err_log_msg(ErrCode, ErrMsg);
                log_info("%s\n", ErrMsg);
                goto exitCode;
            }
        }
    }

    return true;
exitCode:
    log_info("checkModels failed\n");
    return false;
}

bool sensormanager::checkDevs()
{
    int cnt = 0;
    bool ret;

    getRegister(nullptr, 10);
    Sensors sensors, unregistered;
    getSensors(sensors);

    for (auto it=sensors.begin(); it!=sensors.end(); it++)
    {
        SensorNode *dev = *it;
        DevInfo & dev_info = dev->devInfo();
        const DevInfo *info = findDevInfo(dev_info.model, dev_info.port,
                                          dev_info.addr, dev_info.desc);
        if (info)
        {
            dev_info.guid = info->guid;
            dev_info.dev = info->dev;
        }
        else
        {
            unregistered.push_back(dev);
        }
    }

    if (unregistered.size())
    {
        std::list<DevInfo> devs;
        for (auto it=unregistered.begin(); it!=unregistered.end(); it++)
        {
            devs.push_back((*it)->devInfo());
        }

        listenDevRegisterNotify();

        if(!registerDevs(devs))
        {
            ErrCode = REGISTER_DEVICE_FAIL;
            Print_err_log(ErrCode);
            goto exitCode;
        }

        do
        {
            cnt++;

            mtx_.lock();
            for (auto it=unregistered.begin(); it!=unregistered.end(); )
            {
                SensorNode *dev = *it;
                DevInfo & dev_info = dev->devInfo();
                const DevInfo *info = findDevInfo(dev_info.model, dev_info.port,
                                                  dev_info.addr, dev_info.desc);
                if (info)
                {
                    dev_info.guid = info->guid;
                    dev_info.dev = info->dev;
                    it = unregistered.erase(it);
                }
                else
                    it++;
            }
            mtx_.unlock();
            if (unregistered.empty())
            {
                break;
            }
            sleep(1);
        } while (cnt <= 10);
        unLinstenDevRegisterNotify();
        if (unregistered.size())
        {
            ErrCode = REGISTER_DEVICE_FAIL;
            Print_err_log(ErrCode);
            goto exitCode;
        }
    }

    return true;
exitCode:
    log_info("checkDevs failed\n");
    return false;
}

void sensormanager::copyDevInfo(DevInfo &dc, const IDevice *dev)
{
    dc.port = PhysicalLinkManager::mgr()->getPortName(dev->com()->devName());
    dc.addr = dev->devInfo()->addr;
    dc.manuID = dev->devInfo()->manuID;
    dc.manuName = dev->devInfo()->manuName;
    dc.protocolName = dev->devInfo()->protocolName;
    dc.deviceType = dev->devInfo()->deviceType;
    dc.nodeID = dev->devInfo()->nodeID;
    dc.productID = dev->devInfo()->productID;
    dc.desc = dev->devInfo()->desc;
}

void sensormanager::getSensors(sensormanager::Sensors &sensors)
{
    sensors.clear();
    for (auto it=sensors_.begin(); it!=sensors_.end(); it++) {
        for (auto it_d=it->second.begin(); it_d!=it->second.end(); it_d++) {
            sensors.push_back(*it_d);
        }
    }
}

SensorNode *sensormanager::findSensor(const char *dev_guid)
{
    for (auto it=sensors_.begin(); it!=sensors_.end(); it++) {
        for (auto it_d=it->second.begin(); it_d!=it->second.end(); it_d++) {
            SensorNode* sensor = *it_d;
            if (sensor->devInfo().dev.compare(dev_guid) == 0)
                return sensor;
        }
    }
    return nullptr;
}

void sensormanager::onConnect()
{
    DataCenter::onConnect();
}

void sensormanager::onConnectionLost(const char *cause)
{
    DataCenter::onConnectionLost(cause);
}

SensorNode * sensormanager::loadSensor(Value *js, int dev_type)
{
    const char *model = getString(js, "DataCenterModel");
    const char *desc  = getString(js, "Desc", "");
    uint16_t com_index;
    if (dev_type == 0)
    {
        com_index = getInt<uint16_t>(js, "ComIndex", 0);
    }
    else
    {
        const char *com_name = getString(js, "ComName");
        com_index = PhysicalLinkManager::mgr()->getIndexByPort(com_name);
    }

    uint16_t dev_id = getInt<uint16_t>(js, "DevId", 0);
    const ModelItems *items = ModelManger::mgr()->node(model);

    if(items == nullptr)
    {
        sprintf(ErrMsg, "SouthDeviceList.json中数据中心模型文件%s内容为空或格式错误\n", model);
        ErrCode = PARSE_DATACENTERMODE_FAIL;
        Print_err_log_msg(ErrCode, ErrMsg);
        return nullptr;
    }

    IDevice *dev = DeviceManager::mgr()->device(com_index, dev_id, dev_type);
    if(dev == nullptr)
    {
        ErrCode = SOUTHDEVICELIST_DEVICE_IS_NULL;
        sprintf(ErrMsg, "loadSensor dev nullptr, com_index :%d, dev_id :%d\n", com_index, dev_id);
        log_info("%s", ErrMsg);
        Print_err_log_msg(ErrCode, ErrMsg);
        return nullptr;
    }
    else if (dev_type == 1)
    {
        dev_id = dev->devId();
    }

    SensorNode *sensor = new SensorNode();
    //遥控数据项
    Value *js_yk = getChild(js, "CtrlDatas");
    if(js_yk != nullptr)
    {
        for (auto it=js_yk->Begin(); it!=js_yk->End(); it++)
        {
            if (it->IsObject()) {
                for (auto n=it->MemberBegin(); n!=it->MemberEnd(); n++)
                {
                    const char *name = n->name.GetString();
                    const DC::ModelItem* item = ModelManger::findItem(items, name);
                    if (item == nullptr)
                    {
                        ErrCode = DATACENTERMODE_ITEM_IS_NULL;
                        sprintf(ErrMsg, "ComIndex :%d, DevId :%d, CtrlDatas item not include %s\n", com_index, dev_id, name);
                        log_info("%s", ErrMsg);
                        Print_err_log_msg(ErrCode, ErrMsg);
                        goto exitCode;
                    }
                    const char *reg_name = n->value.GetString();

                    if (reg_name[0] == '$')
                        reg_name++;

                    if (!dev->hasYK(reg_name))
                    {
                        ErrCode = SOUTHMODE_ITEM_IS_NULL;
                        sprintf(ErrMsg, "ComIndex :%d, DevId :%d, CtrlDatas reg name %s not find\n", com_index, dev_id, reg_name);
                        log_info("%s", ErrMsg);
                        Print_err_log_msg(ErrCode, ErrMsg);
                        goto exitCode;
                    }

                    if (!sensor->addYkList(name, reg_name))
                    {
                        ErrCode = SOUTHMODE_ITEM_IS_REPEAT;
                        sprintf(ErrMsg, "ComIndex :%d, DevId :%d, CtrlDatas name %s repeat\n", com_index, dev_id, name);
                        log_info("%s", ErrMsg);
                        Print_err_log_msg(ErrCode, ErrMsg);
                        goto exitCode;
                    }
                    else
                    {
                        RegBase* reg = (RegBase*)dev->getYK(reg_name);
                        if (reg)
                        {
                            reg->setEnable(true);
                        }
                    }
                }
            }
        }
    }

    //实时数据
    js = getChild(js, "Datas");
    if(js != nullptr)
    {
        for (auto it = js->Begin(); it != js->End(); ++it)
        {
            if (it->IsObject())
            {
                for (auto n = it->MemberBegin(); n != it->MemberEnd(); ++n)
                {
                    const char *name = n->name.GetString();
                    const DC::ModelItem* item = ModelManger::findItem(items, name);
                    if (item == nullptr)
                    {
                        if (dev_type == 0)
                        {
                            ErrCode = DATACENTERMODE_ITEM_IS_NULL;
                            sprintf(ErrMsg, "ComIndex :%d, DevId :%d, Datas item not include %s\n", com_index, dev_id, name);
                            log_info("%s", ErrMsg);
                            Print_err_log_msg(ErrCode, ErrMsg);
                            goto exitCode;
                        }
                    }

                    const char *reg_name = n->value.GetString();
                    if (reg_name[0] == '$')
                        reg_name++;
                    const RegBase* reg = dev->getMeasure(reg_name);

                    if (reg == nullptr)
                    {
                        ErrCode = SOUTHMODE_ITEM_IS_NULL;
                        sprintf(ErrMsg, "ComIndex :%d, DevId :%d, Datas reg name %s not find\n", com_index, dev_id, reg_name);
                        log_info("%s", ErrMsg);
                        Print_err_log_msg(ErrCode, ErrMsg);
                        goto exitCode;
                    }

                    if (!sensor->addAttr(name, reg))
                    {
                        ErrCode = SOUTHMODE_ITEM_IS_REPEAT;
                        sprintf(ErrMsg, "ComIndex :%d, DevId :%d, Datas name %s repeat\n", com_index, dev_id, name);
                        log_info("%s", ErrMsg);
                        Print_err_log_msg(ErrCode, ErrMsg);
                        goto exitCode;
                    }
                    else
                    {
                        RegBase* reg_ = (RegBase*)reg;
                        if (reg_)
                        {
                            reg_->setEnable(true);
                        }
                    }
                }
            }
        }
    }

    {
        DC::DevInfo & info = sensor->devInfo();
        sensor->setDev(dev);
        copyDevInfo(info, dev);
        info.model = model;
        info.isReport = "0";
        if (desc)
            info.desc = desc;
    }

    return sensor;
exitCode:
    if (sensor)
        delete sensor;
    return nullptr;
}

void sensormanager::sendData(IDevice *dev, const Sensors &sensors, bool force, bool reportType, std::string starttime)
{
    IDevice::Datas yxs;
    IDevice::Datas ycs;
    IDevice::Actions ykinfos;

    dev->getYX(yxs, force);
    dev->getYC(ycs, force);
    dev->getActions(ykinfos);

    //清理全部不需要上传的YX,YC
    for (auto it = ycs.begin(); it != ycs.end(); )
    {
        RegBase* reg = (RegBase*)*it;
        if (reg->enable())
        {
            ++it;
        }
        else
        {
            it = ycs.erase(it);
        }
    }

    for (auto it = yxs.begin(); it != yxs.end(); )
    {
        RegBase* reg = (RegBase*)*it;
        if (reg->enable())
        {
            ++it;
        }
        else
        {
            it = yxs.erase(it);
        }
    }

    for (auto it = sensors.begin(); it != sensors.end(); ++it)
    {
        if (reportType == true)
        {
            //数据定时上报
            realTimeData(*it);
        }
    }

    for (auto it = ykinfos.begin(); it != ykinfos.end(); ++it)
    {
        sendYKData(
            it->app.c_str(),
            std::to_string(newToken()).c_str(),
            it->uid.c_str(),
            it->dev.c_str(),
            it->name.c_str(),
            it->type.c_str(),
            std::to_string(it->cmd).c_str(),
            std::to_string(it->action).c_str(),
            std::to_string(it->mode).c_str(),
            std::to_string(it->timeout).c_str(),
            it->status);
    }
}

bool sensormanager::onMsgArrvd(const char *topic, int topic_len, const char *msg, int msg_len)
{
    bool ret;
    std::string::size_type pos = std::string::npos;
    std::string topic_(topic, topic_len);

    if ((pos = topic_.find("/action/request/*/remoteCtrl")) != std::string::npos)
    {
        //遥控
        std::string app = topic_.substr(0, pos);
        Document doc;
        doc.Parse(msg, static_cast<size_t>(msg_len));
        if (!doc.IsObject())
        {
            log_info("the style of msg is not json\n");
            return false;
        }

        const char *token = getString(doc, "token");
        Value *body = getChild(doc, "body");

        if (body==nullptr || body->IsArray()==false)
        {
            log_info("body is null or is not array\n");
            return false;
        }

        for (auto it=body->Begin(); it!=body->End(); it++)
        {
            if (it->IsObject() == false)
            {
                log_info("body is null or is not array\n");
                return false;
            }
            const char *dev_guid   = getString(it, "dev");
            const char *type       = getString(it, "type");
            const char *name       = getString(it, "name");
            const char *cmd        = getString(it, "cmd");
            const char *action     = getString(it, "action");
            const char *mode       = getString(it, "mode");
            const char *timeout    = getString(it, "timeout");
            const char *uid        = getString(it, "uid");

            int status = -1, action_ = -1;

            if (name == nullptr || dev_guid == nullptr)
            {
                return false;
            }

            if (strcmp(type, "SCO") != 0 && strcmp(type, "DCO") == 0 )
            {
                return false;
            }

            status = atoi((char *)cmd);
            if ((status != 0) && (status != 1) && (status != 2))
            {
                return false;
            }

            action_ = atoi((char *)action);
            if ((action_ != 0) && (action_ != 1) && (action_ != 2))
            {
                return false;
            }

            SensorNode *sensor = findSensorByDevId(dev_guid);
            if (sensor)
            {
                std::string regname = sensor->findYkregname(name);

                if(regname.empty())
                {
                    return false;
                }

                if (action_ == 1)
                {
                    if (uid == NULL)
                    {
                        sensor->dev()->setYK(regname.c_str(), status);
                        sendYKData(app.c_str(), token, uid, dev_guid, name, type, cmd, action, mode, timeout, true);
                    }
                    else
                    {
                        if (false == sensor->dev()->setYK(app.c_str(), dev_guid, name, regname.c_str(), uid, type, status, action_, atoi(mode), atoi(timeout)))
                        {
                            sendYKData(app.c_str(), token, uid, dev_guid, name, type, cmd, action, mode, timeout, false);
                        }
                    }
                }
                else if (uid != NULL)
                {
                    bool ret = sensor->dev()->setPreset(app.c_str(), dev_guid, name, regname.c_str(), uid, type, status, action_, atoi(mode), atoi(timeout));
                    sendYKData(app.c_str(), token, uid, dev_guid, name, type, cmd, action, mode, timeout, ret);
                }
                else{}
            }
            else
            {
                return false;
            }
        }

        return true;
    }

    return false;
}

void sensormanager::realTimeData(SensorNode *sensor)
{
    std::ostringstream ss;
    ss << clientId() << "/notify/event/datacenter/"
       << sensor->devInfo().model << "/" << sensor->devInfo().dev;

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);

    std::string tm = DataCenter::GetTimeStamp();

    writer.StartObject();
    writer.Key("token");
    writer.String(std::to_string(newToken()).c_str());
    writer.Key("timestamp");
    writer.String(tm.c_str());
    writer.Key("data_row");
    writer.String("single");

    writer.Key("body");
    writer.StartArray();

    //实时数据写
    for (auto it=sensor->attrs_.begin(); it!=sensor->attrs_.end(); ++it)
    {
        writer.StartObject();
        writer.Key("name");
        writer.String(it->first.c_str());
        writer.Key("val");
        writer.String(it->second->actived() ? (it->second->toString().c_str()) : ("NULL"));
        writer.Key("quality");
        writer.String(it->second->actived() ?  ("0") : ("1"));
        writer.Key("index");
        writer.String("NULL");
        writer.Key("timestamp");
        writer.String(tm.c_str());
        writer.EndObject();

        if (buffer.GetSize() > MQTT_MAX_SIZE)
        {
            writer.EndArray();
            writer.EndObject();
            sendMsg(ss.str().c_str(), buffer.GetString());

            buffer.Clear();
            writer.Reset(buffer);
            usleep(100000);

            std::string tm = DataCenter::GetTimeStamp();

            writer.StartObject();
            writer.Key("token");
            writer.String(std::to_string(newToken()).c_str());
            writer.Key("timestamp");
            writer.String(tm.c_str());
            writer.Key("data_row");
            writer.String("single");

            writer.Key("body");
            writer.StartArray();
        }
    }
    writer.EndArray();
    writer.EndObject();

    sendMsg(ss.str().c_str(), buffer.GetString());
}

void sensormanager::responseRealTimeData(IDevice::Actions& action)
{
    std::ostringstream ss;
    ss << clientId() << "/notify/event/"
       << action.begin()->app << "/read";

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);

    std::string tm = DataCenter::GetTimeStamp();

    writer.StartObject();
    writer.Key("token");
    writer.String(action.begin()->token.c_str());
    writer.Key("timestamp");
    writer.String(tm.c_str());
    writer.Key("uid");
    writer.String(action.begin()->uid.c_str());

    writer.Key("body");
    writer.StartArray();
    writer.StartObject();
    writer.Key("dev");
    writer.String(action.begin()->dev.c_str());
    writer.Key("datatype");
    writer.String(action.begin()->type.c_str());

    writer.Key("body");
    writer.StartArray();

    //实时数据写
    for (auto it = action.begin(); it != action.end(); ++it)
    {
        writer.StartObject();
        writer.Key("name");
        writer.String(it->name.c_str());
        if (it->status)
        {
            writer.Key("val");
            writer.String(it->reg->actived() ? (it->reg->toString().c_str()) : ("NULL"));
            writer.Key("quality");
            writer.String(it->reg->actived() ?  ("0") : ("1"));
        }
        else
        {
            writer.Key("val");
            writer.String("NULL");
            writer.Key("quality");
            writer.String("1");
        }
        writer.Key("index");
        writer.String("NULL");
        writer.Key("timestamp");
        writer.String(tm.c_str());
        writer.EndObject();

        if (buffer.GetSize() > MQTT_MAX_SIZE)
        {
            writer.EndArray();
            writer.EndObject();
            writer.EndArray();
            writer.EndObject();
            sendMsg(ss.str().c_str(), buffer.GetString());

            buffer.Clear();
            writer.Reset(buffer);
            usleep(100000);

            std::string tm = DataCenter::GetTimeStamp();

            writer.StartObject();
            writer.Key("token");
            writer.String(action.begin()->token.c_str());
            writer.Key("timestamp");
            writer.String(tm.c_str());
            writer.Key("uid");
            writer.String(action.begin()->uid.c_str());

            writer.Key("body");
            writer.StartArray();
            writer.StartObject();
            writer.Key("dev");
            writer.String(action.begin()->dev.c_str());
            writer.Key("datatype");
            writer.String(action.begin()->type.c_str());

            writer.Key("body");
            writer.StartArray();
        }
    }
    writer.EndArray();
    writer.EndObject();

    writer.EndArray();
    writer.EndObject();

    sendMsg(ss.str().c_str(), buffer.GetString());
}

void sensormanager::BoardCastsendErrorInfo(const char *topic, const char *msg)
{
    sendMsg(topic, msg);
}

void sensormanager::SendDevState(const SensorNode *sensor, bool Type)
{
    std::ostringstream ss;
    ss << clientId() << "/notify/event/datacenter/"
       << sensor->devInfo().model << "/" << sensor->devInfo().dev;

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);

    std::string tm = DataCenter::GetTimeStamp();

    writer.StartObject();
    writer.Key("token");
    writer.String(std::to_string(newToken()).c_str());
    writer.Key("timestamp");
    writer.String(tm.c_str());
    writer.Key("data_row");
    writer.String("status");

    writer.Key("body");
    writer.StartArray();

    writer.StartObject();
    writer.Key("name");
    writer.String("online");
    writer.Key("val");
    if(Type)
    {
        writer.String("1");
    }
    else
    {
        writer.String("0");
    }

    writer.Key("timestamp");
    writer.String(tm.c_str());
    writer.EndObject();

    writer.EndArray();
    writer.EndObject();

    sendMsg(ss.str().c_str(), buffer.GetString());
}

void sensormanager::BoardCastsendDevState(const SensorNode *sensor, std::string starttime, bool Type)
{
    std::ostringstream ss;
    ss << clientId() << "/notify/spont/*/"
       << sensor->devInfo().model << "/" << sensor->devInfo().dev;

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);

    std::string tm = DataCenter::GetTimeStamp();

    writer.StartObject();
    writer.Key("token");
    writer.String(std::to_string(newToken()).c_str());
    writer.Key("timestamp");
    writer.String(tm.c_str());
    writer.Key("datatype");
    writer.String("7");

    writer.Key("body");
    writer.StartArray();

    writer.StartObject();
    writer.Key("model");
    writer.String(sensor->devInfo().model.c_str());
    writer.Key("dev");
    writer.String(sensor->devInfo().dev.c_str());
    writer.Key("event");

    if(Type)
    {
        writer.String("Online");
    }
    else
    {
        writer.String("Offline");
    }

    writer.Key("starttime");
    writer.String(starttime.c_str());
    writer.Key("endtime");
    writer.String("");
    writer.Key("timestamp");
    writer.String(tm.c_str());
    writer.EndObject();

    writer.EndArray();
    writer.EndObject();

    sendMsg(ss.str().c_str(), buffer.GetString());
}

void sensormanager::sendYKData(const char* app, const char* token, const char *uid, const char *dev, const char *name, const char *type, const char *cmd, const char *action, const char *mode, const char *timeout, bool Status)
{
    bool rc = false;
    std::ostringstream ss;
    ss << clientId() << "/action/response/" << app << "/remoteCtrl";

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);

    std::string tm = DataCenter::GetTimeStamp();

    writer.StartObject();
    writer.Key("token");
    writer.String(token);
    writer.Key("timestamp");
    writer.String(tm.c_str());

    writer.Key("body");
    writer.StartArray();

    {
        writer.StartObject();
        if (uid)
        {
            writer.Key("uid");
            writer.String(uid);
        }
        writer.Key("name");
        writer.String(name);
        writer.Key("dev");
        writer.String(dev);
        writer.Key("type");
        writer.String(type);
        writer.Key("cmd");
        writer.String(cmd);
        writer.Key("action");
        writer.String(action);
        writer.Key("mode");
        writer.String(mode);
        writer.Key("timeout");
        writer.String(timeout);
        writer.Key("status");

        if(Status == true)
            writer.String("OK");
        else
            writer.String("FAILURE");

        writer.EndObject();
        rc = true;
    }

    writer.EndArray();
    writer.EndObject();

    if (rc)
    {
        sendMsg(ss.str().c_str(), buffer.GetString());
    }
}

SensorNode *sensormanager::findSensorByDevId(const char *dev_id)
{
    return findSensor(dev_id);
}

std::vector<SensorNode*> sensormanager::findSensorByDevAddr(const char *dev_addr)
{
    std::vector<SensorNode*> v;
    Sensors sensors;

    getSensors(sensors);

    for (auto it = sensors.begin(); it != sensors.end(); it++)
    {
        if ((*it)->devInfo().addr.compare(dev_addr) == 0)
        {
            v.push_back(*it);
        }
    }

    return v;
}
